iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0
自我挑戰組

重新複習JavaScript系列 第 17

[Day -17] 遍歷周邊 DOM 節點

  • 分享至 

  • xImage
  •  

我們先來看一張DOM Tree的圖

Imgur

DOM 節點有分層的概念,節點與節點之間的關係我們大致上可以分成兩種:

  • 父子關係

    除了 document 之外,每一個節點都會有個上層的節點,我們通常稱之為「父節點」 (Parent node),而相對地,從屬於自己下層的節點,就會稱為「子節點」(Child node)。

  • 兄弟關係:有同一個「父節點」的節點,那麼他們彼此之間就是「兄弟節點」(Siblings node)。

有時候你無法直接用名稱或選擇器找到節點,這時候就必須透過關係

簡單解釋一下這個流程,依然拿之前的案例來做說明:

Imgur

這是一篇文章其中有一篇文章的標題是Professional Sports ,當今天我必須要回傳在這個標題裡所有放在<li>的文字內容(別問我為什麼要回傳XD),這時候在DOM Tree的查找路徑會是:

<h4>Professional Sports</h4> 出發。

找到他的兄弟<ul>

在找到<ul>的children(孩子)<li>

而這個從樹狀結構裡查找資料的動作就是我們今天的主題**traverse**

選出周邊的元素節點

我們來看一下語法:

Imgur

  • parentElement:返回元素的父級元素。
  • nextElementSibling:返回元素的下一個兄弟元素。
  • previousElementSibling:返回元素的前一個兄弟元素。
  • firstElementChild:返回元素的第一個子元素。
  • lastElementChild:返回元素的最後一個子元素。

我們在之前那個案例來實際操作一下吧:

Imgur

其中要特別說一下最一開始的HTMLCollection(5) ,還記得昨天我們有說到NodeList 嗎?

如果忘記也沒關係,我們在看一下:

NodeList 很類似於Array ,但它並不是真正的 Array。

它不能新增刪除元素,只有幾個簡單的唯讀操作:

  • 查看長度 length
  • 遍歷內容 forEach
  • 使用 index 來存取特定項目

HTMLCollection()NodeList 很類似於Array ,但它並不是真正的 Array的,我們有一個專有的名詞,叫做Array-like object 但一般我們都會叫他Array-like

詳細的內容這邊就不說了,有興趣的朋友再去網路上看。

另外一組語法

大家如果在網路上看資料時,想必都會看到另外一組語法:

parentNodenextSiblingpreviousSiblingfirstChildlastChild

為什麼會有兩組呢?我們先來看一下實際操作後大家應該就會知道差別在哪裡了:

Imgur

為什麼這組語法出來的結果會有這麼多的text啊?主要還是我們在排版程式碼時的「換行/縮排」,會產生隱藏的文字節點。詳細內容大家可以到 MDN 看,我這邊就是簡單提一下。

至於這兩種語法的區別,我個人的解讀是在於它們如何處理節點。其中 parentElementnextElementSibling 等屬性和方法只會考慮元素節點(Element Node),而忽略其他類型的節點,如文字節點、註釋節點等。而 parentNodenextSibling 等屬性和方法則會考慮所有類型的節點。

這是我自己的解讀,如果有錯還請大家指教!

我在知乎跟稀土上有看到兩篇文章,大家也可以參考一下:知乎參考文章稀土參考文章


陣列遍歷

當我們想對一個陣列裡的每個元素都執行某個方法時,除了傳統的 for 迴圈外,還可以使用什麼呢?就讓我們一起看下去:

for

使用情境:

  • 用於執行迴圈次數「明確」的狀況
  • 例如:印出陣列 [0, 1, 2] 中的每一個數字
for(let i = 0; i < 3; i++){
    console.log(i);
}
// 0
// 1
// 2

arr.forEach

使用情境:

  • 用法與 for loop 類似,差別在於 forEach 不需設定索引的邊界條件
  • 缺點是無法使用 break 中斷迴圈,或 return 返回值等等

語法:

array.forEach(function(currentValue, index, arr), thisValue)

currentValue :當前陣列元素的值

index :當前陣列元素的 index

arr :當前陣列本身。

我們用一個範例來解釋:

const scores = [1, 2, 3]
let sum = 0
scores.forEach(function (score, index) {
  console.log(`現在輸到第 ${index} 項,值是 ${score}`)
  sum += score
  console.log(`現在總和是: ${sum}`)
})

由於這個函式只會在 forEach 裡面運作,別的地方用不到,因此沒有特別取名的必要。因此可以使用箭頭函式:

const scores = [1, 2, 3]
let sum = 0
scores.forEach((score, index) => {
  console.log(`現在輸到第 ${index} 項,值是 ${score}`)
  sum += score
  console.log(`現在總和是: ${sum}`)
})

其結果為:

Imgur
有兩點要注意:

  • forEach 沒有回傳值:
    forEach方法的角色是領路人,把陣列中的每個元素依序交給 function 處理,交付完它的任務就結束了。
  • function 的參數可以自由命名
    慣用的命名手法是陣列用複數單字命名 (例如 words, scores ),代表單一陣列元素的參數就用單數命名 (例如 word, score)。
    另外 item 和 element 也常被用來代表單一元素。

for…of

語法:

for (variable of iterable)
  statement
  • variable :在每次迭代中從序列中接收一個值。可以是使用 const、let 或 var 進行聲明,也可以是分配目標(例如之前聲明的變數、物件屬性或解構賦值模式)。
  • iterable:一個可迭代的 object。 作為迴圈運作的值序列的來源。
  • statement :在每次迭代中要執行的陳述式。

一樣我們用一個範例來解釋:

const array1 = ['a', 'b', 'c'];

for (const element of array1) {
  console.log(element);
}

// Expected output: "a"
// Expected output: "b"
// Expected output: "c"

至於跟他很像的for…in我很少用到比較沒有那麼清楚,這邊附上PJ大神所寫的文章讓大家參考。

map

語法:

const newArray = array.map((currentValue, index, array) => {
  // return newValue based on currentValue
});
  • currentValue: 目前迭代的陣列元素的值。
  • index (選填): 目前迭代的陣列元素的索引。
  • array (選填): 原始的陣列。

map() 方法的主要特點是它不會改變原始陣列,而是返回一個新的陣列,其中每個元素都是經過回呼函式處理後的結果。

看個案例會更加清楚:

const array1 = [1, 4, 9, 16];

// Pass a function to map
const map1 = array1.map((x) => x * 2);

console.log(map1);
// Expected output: Array [2, 8, 18, 32]

終於寫完了,但有幾個遍歷的方法我並沒有寫出來,是因為這邊所列的都是我在這段學習過程中有使用到且還記得的><”

沒寫出來的應該是我沒用過、或是我真的忘了。

但很多資料也都只寫到這些,應該還行啦。


上一篇
[Day -16] DOM Node 的建立、刪除與修改
下一篇
[Day -18] 事件機制的原理
系列文
重新複習JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言